#ifndef FF_DEFINED
#define FF_DEFINED	80286	/* Revision ID：版本标识（80286 对应 R0.15） */

#ifdef __cplusplus
extern "C" {
#endif

#include "ffconf.h"	
#if FF_DEFINED != FFCONF_DEF
#error Wrong configuration file (ffconf.h).
#endif


/*----------------------------------------------------------------------------/
/  1. FatFs API 核心数据类型定义                                              /
/  （适配不同编译器/标准，确保跨平台兼容性）                                  /
/----------------------------------------------------------------------------*/

#if defined(_WIN32)		/* Windows VC++（仅用于开发调试，嵌入式场景不适用） */
#define FF_INTDEF 2
#include <windows.h>
typedef unsigned __int64 QWORD;
#include <float.h>
#define isnan(v) _isnan(v)
#define isinf(v) (!_finite(v))

#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus)	/* C99 及以上标准（嵌入式常用） */
#define FF_INTDEF 2
#include <stdint.h>
typedef unsigned int	UINT;	/* 无符号int（需确保为16/32位，嵌入式中通常32位） */
typedef unsigned char	BYTE;	/* 无符号char（固定8位，存储字节数据） */
typedef uint16_t		WORD;	/* 无符号16位整数（存储扇区数、短文件名等） */
typedef uint32_t		DWORD;	/* 无符号32位整数（存储簇号、文件大小等） */
typedef uint64_t		QWORD;	/* 无符号64位整数（exFAT/大存储场景用） */
typedef WORD			WCHAR;	/* UTF-16 字符类型（长文件名场景用） */

#else  	/* C99 之前的标准（老旧编译器兼容） */
#define FF_INTDEF 1
typedef unsigned int	UINT;	/* 无符号int */
typedef unsigned char	BYTE;	/* 无符号char（8位） */
typedef unsigned short	WORD;	/* 无符号16位整数 */
typedef unsigned long	DWORD;	/* 无符号32位整数 */
typedef WORD			WCHAR;	/* UTF-16 字符类型 */
#endif


/*----------------------------------------------------------------------------/
/  2. 文件大小和扇区地址（LBA）类型定义                                      /
/  （根据是否开启 exFAT/64位LBA 自动适配）                                    /
/----------------------------------------------------------------------------*/

#if FF_FS_EXFAT 	/* 开启 exFAT 功能（支持4GB以上大文件） */
#if FF_INTDEF != 2
#error exFAT feature wants C99 or later
#endif
typedef QWORD FSIZE_t;	/* 文件大小类型（64位，支持最大16EB） */
#if FF_LBA64
typedef QWORD LBA_t;	/* 扇区地址类型（64位，支持大存储设备） */
#else
typedef DWORD LBA_t;	/* 扇区地址类型（32位，支持最大2TB） */
#endif
#else 	/* 未开启 exFAT（仅支持FAT12/FAT16/FAT32，最大4GB文件） */
#if FF_LBA64
#error exFAT needs to be enabled when enable 64-bit LBA
#endif
typedef DWORD FSIZE_t;	/* 文件大小类型（32位，最大4GB） */
typedef DWORD LBA_t;	/* 扇区地址类型（32位，最大2TB） */
#endif


/*----------------------------------------------------------------------------/
/  3. 路径字符串类型（TCHAR）定义                                             /
/  （根据长文件名（LFN）和编码格式自动适配）                                  /
/----------------------------------------------------------------------------*/

#if FF_USE_LFN && FF_LFN_UNICODE == 1 	/* 长文件名+UTF-16LE编码（小端，无BOM，Windows默认格式） */
typedef WCHAR TCHAR;
#define _T(x) L ## x		/* 字符串转UTF-16LE宏（如 _T("文件.txt") → L"文件.txt"，宽字符格式） */
#define _TEXT(x) L ## x
#elif FF_USE_LFN && FF_LFN_UNICODE == 2	/* 长文件名+UTF-16BE编码（大端，无BOM，较少用，多为特定设备） */
typedef WCHAR TCHAR;
#define _T(x) L ## x		/* 字符串转UTF-16BE宏（宽字符格式，需注意字节序转换） */
#define _TEXT(x) L ## x
#elif FF_USE_LFN && FF_LFN_UNICODE == 3	/* 长文件名+UTF-8编码（无BOM，嵌入式首选，兼容多语言） */
typedef char TCHAR;
#define _T(x) u8 ## x		/* 字符串转UTF-8宏（如 _T("文件.txt") → u8"文件.txt"，单字节序列） */
#define _TEXT(x) u8 ## x
#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3)
#error Wrong FF_LFN_UNICODE setting (must be 0-3)
#else									/* 不启用长文件名（仅支持8.3短文件名，使用ANSI/OEM编码，由FF_CODE_PAGE指定） */
typedef char TCHAR;
#define _T(x) x			/* 直接使用ANSI字符串（如 _T("test.txt") → "test.txt"，依赖本地代码页） */
#define _TEXT(x) x
#endif

/*----------------------------------------------------------------------------/
/  4. 卷管理相关定义                                                         /
/  （多分区/自定义卷标场景使用）                                              /
/----------------------------------------------------------------------------*/

#if FF_MULTI_PARTITION		/* 启用多分区配置（一个物理驱动器分多个逻辑分区） */
typedef struct {
	BYTE pd;	/* 物理驱动器号（如0=第一个SPI Flash，1=SD卡） */
	BYTE pt;	/* 分区号（0=自动检测，1-4=强制指定分区） */
} PARTITION;
extern PARTITION VolToPart[];	/* 卷-分区映射表（用户需自行实现，如卷C:对应分区0） */
#endif

#if FF_STR_VOLUME_ID		/* 启用字符串格式卷标（如"C:""D:"而非默认0:1:） */
#ifndef FF_VOLUME_STRS
extern const char* VolumeStr[FF_VOLUMES];	/* 用户自定义卷标数组（如 VolumeStr[0] = "C:"） */
#endif
#endif


/*----------------------------------------------------------------------------/
/  5. 核心结构体定义                                                         /
/  （FatFs 操作的核心对象，需理解成员含义以避免使用错误）                      /
/----------------------------------------------------------------------------*/

/**
 * @brief  文件系统对象（FATFS）
 * @note   每个逻辑卷（如C:）对应一个FATFS对象，存储文件系统的核心配置和状态
 */
typedef struct {
	BYTE	fs_type;		/* 文件系统类型（0=未挂载，1=FAT12，2=FAT16，3=FAT32，4=exFAT） */
	BYTE	pdrv;			/* 关联的物理驱动器号（如0=NOR Flash） */
	BYTE	ldrv;			/* 逻辑驱动器号（仅FF_FS_REENTRANT（可重入）模式使用） */
	BYTE	n_fats;			/* FAT表数量（1或2，2=冗余备份，增强可靠性） */
	BYTE	wflag;			/* 缓存窗口状态（b0=脏标记，需同步到存储设备） */
	BYTE	fsi_flag;		/* FSINFO状态（b7=禁用，b0=脏标记，FAT32用） */
	WORD	id;				/* 卷挂载ID（防止多卷混淆） */
	WORD	n_rootdir;		/* 根目录项数量（仅FAT12/FAT16有效） */
	WORD	csize;			/* 簇大小（单位：扇区，如4=4×512=2KB簇） */
#if FF_MAX_SS != FF_MIN_SS
	WORD	ssize;			/* 扇区大小（512/1024/2048/4096字节，你的NOR Flash是4096） */
#endif
#if FF_USE_LFN
	WCHAR*	lfnbuf;			/* 长文件名工作缓冲区（用户需提供，存储长文件名临时数据） */
#endif
#if FF_FS_EXFAT
	BYTE*	dirbuf;			/* exFAT目录项临时缓冲区（exFAT模式专用） */
#endif
#if !FF_FS_READONLY
	DWORD	last_clst;		/* 最后分配的簇号（优化簇分配速度） */
	DWORD	free_clst;		/* 空闲簇数量（计算剩余空间用） */
#endif
#if FF_FS_RPATH
	DWORD	cdir;			/* 当前目录起始簇（0=根目录） */
#if FF_FS_EXFAT
	DWORD	cdc_scl;		/* 包含目录的起始簇（cdir非0时有效） */
	DWORD	cdc_size;		/* 包含目录大小+链状态（exFAT专用） */
	DWORD	cdc_ofs;		/* 包含目录中的偏移（exFAT专用） */
#endif
#endif
	DWORD	n_fatent;		/* FAT表项数量（簇数+2） */
	DWORD	fsize;			/* 每个FAT表占用的扇区数 */
	LBA_t	volbase;		/* 卷起始扇区（物理驱动器上的偏移） */
	LBA_t	fatbase;		/* FAT表起始扇区 */
	LBA_t	dirbase;		/* 根目录起始扇区（FAT12/FAT16）或簇（FAT32/exFAT） */
	LBA_t	database;		/* 数据区起始扇区 */
#if FF_FS_EXFAT
	LBA_t	bitbase;		/* exFAT分配位图起始扇区 */
#endif
	LBA_t	winsect;		/* 当前缓存窗口中的扇区号（0=无效） */
	BYTE	win[FF_MAX_SS];	/* 磁盘访问缓存窗口（存储目录/FAT表数据，大小=最大扇区数） */
} FATFS;

/**
 * @brief  对象标识结构体（FFOBJID）
 * @note   存储文件/目录的核心标识信息，是FIL和DIR结构体的基础成员
 */
typedef struct {
	FATFS*	fs;				/* 关联的文件系统对象指针（如指向C:对应的FATFS） */
	WORD	id;				/* 卷挂载ID（与FATFS.id一致，验证有效性） */
	BYTE	attr;			/* 对象属性（AM_RDO/AM_DIR等，区分文件/目录/只读等） */
	BYTE	stat;			/* 对象链状态（0=不连续，2=连续，3=碎片） */
	DWORD	sclust;			/* 对象数据起始簇（0=无簇/根目录） */
	FSIZE_t	objsize;		/* 对象大小（文件大小/目录占用空间） */
#if FF_FS_EXFAT
	DWORD	n_cont;			/* 第一个碎片大小-1（exFAT专用） */
	DWORD	n_frag;			/* 最后一个碎片需写入FAT的大小（exFAT专用） */
	DWORD	c_scl;			/* 包含目录的起始簇（sclust非0时有效） */
	DWORD	c_size;			/* 包含目录大小+链状态（exFAT专用） */
	DWORD	c_ofs;			/* 包含目录中的偏移（文件对象有效） */
#endif
#if FF_FS_LOCK
	UINT	lockid;			/* 文件锁ID（多线程场景防止并发冲突） */
#endif
} FFOBJID;

/**
 * @brief  文件对象结构体（FIL）
 * @note   打开文件后生成的句柄，所有文件操作（读/写/定位）都依赖该对象
 * @warning 必须通过f_open初始化，使用后通过f_close关闭，避免资源泄露
 */
typedef struct {
	FFOBJID	obj;			/* 对象标识（第一个成员，用于检测无效指针） */
	BYTE	flag;			/* 文件状态标志（如是否可写、是否打开等） */
	BYTE	err;			/* 错误标志（存储最近一次操作的错误码） */
	FSIZE_t	fptr;			/* 文件读写指针（当前操作位置，初始为0） */
	DWORD	clust;			/* 当前指针所在的簇（fptr非0时有效） */
	LBA_t	sect;			/* 缓存窗口中的扇区号（0=无效） */
#if !FF_FS_READONLY
	LBA_t	dir_sect;		/* 目录项所在扇区（非exFAT模式用） */
	BYTE*	dir_ptr;		/* 目录项在缓存窗口中的指针（非exFAT模式用） */
#endif
#if FF_USE_FASTSEEK
	DWORD*	cltbl;			/* 簇链接映射表指针（快速定位用，应用层设置） */
#endif
#if !FF_FS_TINY
	BYTE	buf[FF_MAX_SS];	/* 文件私有读写缓存（大小=最大扇区数，如4096字节） */
#endif
} FIL;

/**
 * @brief  目录对象结构体（DIR）
 * @note   打开目录后生成的句柄，用于遍历目录下的文件/子目录
 * @warning 必须通过f_opendir初始化，使用后通过f_closedir关闭
 */
typedef struct {
	FFOBJID	obj;			/* 对象标识（关联的文件系统和目录信息） */
	DWORD	dptr;			/* 目录读写偏移（遍历进度） */
	DWORD	clust;			/* 当前遍历的簇 */
	LBA_t	sect;			/* 当前缓存的扇区号（0=遍历结束） */
	BYTE*	dir;			/* 目录项在缓存窗口中的指针 */
	BYTE	fn[12];			/* 短文件名缓存（8.3格式：8字节文件名+3字节扩展名+1字节状态） */
#if FF_USE_LFN
	DWORD	blk_ofs;		/* 当前处理的目录项块偏移（长文件名专用） */
#endif
#if FF_USE_FIND
	const TCHAR* pat;		/* 文件名匹配模式（f_findfirst/f_findnext用） */
#endif
} DIR;

/**
 * @brief  文件信息结构体（FILINFO）
 * @note   存储文件/目录的属性信息（大小、修改时间、属性等），通过f_stat/f_readdir获取
 */
typedef struct {
	FSIZE_t	fsize;			/* 文件大小（目录大小为0） */
	WORD	fdate;			/* 修改日期（格式：年11-0位 + 月4-0位 + 日5-0位） */
	WORD	ftime;			/* 修改时间（格式：时5-0位 + 分6-0位 + 秒5-0位（×2）） */
	BYTE	fattrib;		/* 文件属性（AM_RDO/AM_DIR/AM_HID等组合） */
#if FF_USE_LFN
	TCHAR	altname[FF_SFN_BUF + 1];/* 替代短文件名（长文件名场景用） */
	TCHAR	fname[FF_LFN_BUF + 1];	/* 主文件名（长文件名/短文件名） */
#else
	TCHAR	fname[12 + 1];	/* 文件名（仅短文件名，8.3格式+终止符） */
#endif
} FILINFO;

/**
 * @brief  格式化参数结构体（MKFS_PARM）
 * @note   用于f_mkfs函数，自定义格式化配置（如文件系统类型、簇大小等）
 */
typedef struct {
	BYTE fmt;			/* 格式化类型（FM_FAT/FM_FAT32/FM_EXFAT/FM_ANY/FM_SFD） */
	BYTE n_fat;			/* FAT表数量（1或2） */
	UINT align;			/* 数据区对齐（单位：扇区） */
	UINT n_root;		/* 根目录项数量（仅FAT12/FAT16有效） */
	DWORD au_size;		/* 簇大小（单位：字节，如4096=4KB） */
} MKFS_PARM;


/*----------------------------------------------------------------------------/
/  6. 函数返回码枚举（FRESULT）                                              /
/  （所有FatFs API的返回值，用于判断操作结果，调试核心）                      /
/----------------------------------------------------------------------------*/
typedef enum {
	FR_OK = 0,				/* (0) 操作成功 */
	FR_DISK_ERR,			/* (1) 底层磁盘I/O错误（如SPI通信失败） */
	FR_INT_ERR,				/* (2) 内部逻辑错误（断言失败，通常是配置错误） */
	FR_NOT_READY,			/* (3) 物理驱动器未就绪（如Flash未初始化，SFUD识别失败） */
	FR_NO_FILE,				/* (4) 找不到文件（路径或文件名错误，如show_file时文件不存在） */
	FR_NO_PATH,				/* (5) 找不到路径（目录不存在，如mk_file时子目录未创建） */
	FR_INVALID_NAME,		/* (6) 文件名格式无效（含*?:"<>|等特殊字符） */
	FR_DENIED,				/* (7) 访问被拒绝（如文件只读、目录满） */
	FR_EXIST,				/* (8) 文件已存在（FA_CREATE_NEW模式下创建已存在文件） */
	FR_INVALID_OBJECT,		/* (9) 文件/目录对象无效（如用未打开的FIL/DIR操作） */
	FR_WRITE_PROTECTED,		/* (10) 物理驱动器只读（如Flash写保护引脚拉低） */
	FR_INVALID_DRIVE,		/* (11) 逻辑驱动器号无效（如访问D:但仅挂载了C:） */
	FR_NOT_ENABLED,			/* (12) 卷无工作缓冲区（配置错误，如LFN缓冲区未提供） */
	FR_NO_FILESYSTEM,		/* (13) 无有效文件系统（新Flash未格式化，需执行mkfs） */
	FR_MKFS_ABORTED,		/* (14) 格式化中断（如缓冲区不足、磁盘错误） */
	FR_TIMEOUT,				/* (15) 卷访问超时（多线程场景未获取锁） */
	FR_LOCKED,				/* (16) 文件被锁定（多线程并发访问冲突） */
	FR_NOT_ENOUGH_CORE,		/* (17) 长文件名缓冲区分配失败（内存不足） */
	FR_TOO_MANY_OPEN_FILES,	/* (18) 打开文件数超出限制（FF_FS_LOCK配置过小） */
	FR_INVALID_PARAMETER	/* (19) 参数无效（如传递NULL指针、非法路径） */
} FRESULT;


/*----------------------------------------------------------------------------/
/  7. FatFs 核心API函数声明                                                  /
/  （嵌入式开发常用函数已标注使用场景，对应你的代码功能）                      /
/----------------------------------------------------------------------------*/

/**
 * @brief  打开或创建文件
 * @param  fp: 文件对象指针（需提前定义，如FIL file）
 * @param  path: 文件路径（如 _T("C:/test.txt")）
 * @param  mode: 打开模式（FA_READ/FA_WRITE 与 FA_CREATE_ALWAYS等组合，你的mk_file用FA_WRITE|FA_CREATE_ALWAYS）
 * @return FRESULT: 操作结果（FR_OK=成功）
 */
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode);

/**
 * @brief  关闭已打开的文件对象
 * @param  fp: 文件对象指针（已通过f_open初始化）
 * @return FRESULT: 操作结果（FR_OK=成功）
 * @note   必须调用，否则会导致文件缓存未同步、资源泄露
 */
FRESULT f_close (FIL* fp);

/**
 * @brief  从文件读取数据
 * @param  fp: 文件对象指针（已以FA_READ模式打开）
 * @param  buff: 数据接收缓冲区（如你的file_buf）
 * @param  btr: 期望读取的字节数（如1024）
 * @param  br: 实际读取的字节数（输出参数，需提前定义UINT变量）
 * @return FRESULT: 操作结果（FR_OK=成功）
 * @note   你的show_file函数核心调用此函数
 */
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br);

/**
 * @brief  向文件写入数据
 * @param  fp: 文件对象指针（已以FA_WRITE模式打开）
 * @param  buff: 待写入的数据缓冲区
 * @param  btw: 期望写入的字节数
 * @param  bw: 实际写入的字节数（输出参数）
 * @return FRESULT: 操作结果（FR_OK=成功）
 * @note   你的mk_file函数核心调用此函数（或f_printf）
 */
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw);

/**
 * @brief  移动文件读写指针（文件定位/跳转）
 * @param  fp: 文件对象指针（已打开）
 * @param  ofs: 目标偏移量（相对于文件起始位置）
 * @return FRESULT: 操作结果（FR_OK=成功）
 * @note   可用于重写文件、跳过部分内容读取
 */
FRESULT f_lseek (FIL* fp, FSIZE_t ofs);

/**
 * @brief  截断文件（修改文件大小）
 * @param  fp: 文件对象指针（已以FA_WRITE模式打开）
 * @return FRESULT: 操作结果（FR_OK=成功）
 * @note   常用于清空文件内容（ofs=0时）或缩减文件大小
 */
FRESULT f_truncate (FIL* fp);

/**
 * @brief  同步文件缓存（强制写入存储设备）
 * @param  fp: 文件对象指针（已以FA_WRITE模式打开）
 * @return FRESULT: 操作结果（FR_OK=成功）
 * @note   写入重要数据后建议调用，防止掉电丢失（Flash写入有缓存）
 */
FRESULT f_sync (FIL* fp);

/**
 * @brief  打开目录
 * @param  dp: 目录对象指针（需提前定义，如DIR dir）
 * @param  path: 目录路径（如 _T("C:/data")）
 * @return FRESULT: 操作结果（FR_OK=成功）
 * @note   你的ls_c函数核心调用此函数（打开C:根目录）
 */
FRESULT f_opendir (DIR* dp, const TCHAR* path);

/**
 * @brief  关闭已打开的目录对象
 * @param  dp: 目录对象指针（已通过f_opendir初始化）
 * @return FRESULT: 操作结果（FR_OK=成功）
 * @note   必须调用，释放目录资源
 */
FRESULT f_closedir (DIR* dp);

/**
 * @brief  读取目录项（遍历文件/子目录）
 * @param  dp: 目录对象指针（已打开）
 * @param  fno: 文件信息结构体指针（存储读取到的文件/目录信息）
 * @return FRESULT: 操作结果（FR_OK=成功，fno.fname[0]=0表示遍历结束）
 * @note   你的list_directory_files函数核心调用此函数
 */
FRESULT f_readdir (DIR* dp, FILINFO* fno);

/**
 * @brief  查找目录下第一个匹配的文件
 * @param  dp: 目录对象指针
 * @param  fno: 文件信息结构体指针
 * @param  path: 目录路径
 * @param  pattern: 匹配模式（如 _T("*.txt") 匹配所有txt文件）
 * @return FRESULT: 操作结果（FR_OK=成功）
 */
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern);

/**
 * @brief  查找目录下下一个匹配的文件
 * @param  dp: 目录对象指针（已通过f_findfirst初始化）
 * @param  fno: 文件信息结构体指针
 * @return FRESULT: 操作结果（FR_OK=成功，fno.fname[0]=0表示无更多匹配）
 */
FRESULT f_findnext (DIR* dp, FILINFO* fno);

/**
 * @brief  创建子目录
 * @param  path: 目录路径（如 _T("C:/data/log")）
 * @return FRESULT: 操作结果（FR_OK=成功）
 * @note   创建多级目录需逐级创建（如先创建data，再创建data/log）
 */
FRESULT f_mkdir (const TCHAR* path);

/**
 * @brief  删除文件或空目录
 * @param  path: 文件或目录路径
 * @return FRESULT: 操作结果（FR_OK=成功）
 * @note   目录必须为空才能删除，你的del_file/del_dir函数核心调用此函数（del_dir本质是f_unlink）
 */
FRESULT f_unlink (const TCHAR* path);

/**
 * @brief  重命名/移动文件或目录
 * @param  path_old: 原路径
 * @param  path_new: 新路径
 * @return FRESULT: 操作结果（FR_OK=成功）
 */
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new);

/**
 * @brief  获取文件/目录的属性信息
 * @param  path: 文件或目录路径
 * @param  fno: 文件信息结构体指针（存储结果）
 * @return FRESULT: 操作结果（FR_OK=成功）
 */
FRESULT f_stat (const TCHAR* path, FILINFO* fno);

/**
 * @brief  修改文件/目录的属性
 * @param  path: 文件或目录路径
 * @param  attr: 目标属性（AM_RDO/AM_DIR等组合）
 * @param  mask: 属性掩码（指定哪些属性需要修改）
 * @return FRESULT: 操作结果（FR_OK=成功）
 */
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask);

/**
 * @brief  修改文件/目录的时间戳
 * @param  path: 文件或目录路径
 * @param  fno: 存储新时间戳的结构体（仅fdate/ftime有效）
 * @return FRESULT: 操作结果（FR_OK=成功）
 */
FRESULT f_utime (const TCHAR* path, const FILINFO* fno);

/**
 * @brief  切换当前目录
 * @param  path: 目标目录路径
 * @return FRESULT: 操作结果（FR_OK=成功）
 */
FRESULT f_chdir (const TCHAR* path);

/**
 * @brief  切换当前驱动器
 * @param  path: 目标驱动器路径（如 _T("D:")）
 * @return FRESULT: 操作结果（FR_OK=成功）
 */
FRESULT f_chdrive (const TCHAR* path);

/**
 * @brief  获取当前目录路径
 * @param  buff: 存储路径的缓冲区
 * @param  len: 缓冲区长度
 * @return FRESULT: 操作结果（FR_OK=成功）
 */
FRESULT f_getcwd (TCHAR* buff, UINT len);

/**
 * @brief  获取驱动器空闲簇数量（计算剩余空间）
 * @param  path: 驱动器路径（如 _T("C:")）
 * @param  nclst: 空闲簇数量（输出参数）
 * @param  fatfs: 文件系统对象指针（输出参数，关联的FATFS）
 * @return FRESULT: 操作结果（FR_OK=成功）
 * @note   剩余空间 = 空闲簇数 × 簇大小（如nclst=1000，簇大小4KB → 剩余3.9MB）
 */
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs);

/**
 * @brief  获取卷标和序列号
 * @param  path: 驱动器路径
 * @param  label: 存储卷标的缓冲区
 * @param  vsn: 存储卷序列号的指针（输出参数）
 * @return FRESULT: 操作结果（FR_OK=成功）
 */
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn);

/**
 * @brief  设置卷标
 * @param  label: 新卷标（如 _T("NOR_FLASH")）
 * @return FRESULT: 操作结果（FR_OK=成功）
 */
FRESULT f_setlabel (const TCHAR* label);

/**
 * @brief  将文件数据转发到流（如串口、网络）
 * @param  fp: 文件对象指针（已以FA_READ模式打开）
 * @param  func: 数据处理回调函数（如串口发送函数）
 * @param  btf: 期望转发的字节数
 * @param  bf: 实际转发的字节数（输出参数）
 * @return FRESULT: 操作结果（FR_OK=成功）
 */
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf);

/**
 * @brief  为文件分配连续簇（优化读写速度）
 * @param  fp: 文件对象指针（已以FA_WRITE模式打开）
 * @param  fsz: 目标文件大小
 * @param  opt: 分配选项
 * @return FRESULT: 操作结果（FR_OK=成功）
 */
FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt);

/**
 * @brief  挂载/卸载逻辑驱动器
 * @param  fs: 文件系统对象指针（挂载时传入FATFS地址，卸载时传入NULL）
 * @param  path: 驱动器路径（如 _T("C:")）
 * @param  opt: 挂载选项（1=立即挂载，0=延迟挂载）
 * @return FRESULT: 操作结果（FR_OK=成功）
 * @note   你的mnt函数核心调用此函数（挂载C:），卸载用f_mount(NULL, "C:", 1)
 */
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt);

/**
 * @brief  创建FAT文件系统（格式化）
 * @param  path: 驱动器路径（如 _T("C:")）
 * @param  opt: 格式化参数指针（NULL=默认配置）
 * @param  work: 工作缓冲区（大小≥1个扇区，如你的mkfs_work_buf）
 * @param  len: 工作缓冲区长度
 * @return FRESULT: 操作结果（FR_OK=成功）
 * @note   你的mk_file函数依赖此函数（新Flash需先格式化才能创建文件）
 */
FRESULT f_mkfs (const TCHAR* path, const MKFS_PARM* opt, void* work, UINT len);

/**
 * @brief  磁盘分区（将物理驱动器划分为多个逻辑分区）
 * @param  pdrv: 物理驱动器号
 * @param  ptbl: 分区表（存储各分区起始扇区和大小）
 * @param  work: 工作缓冲区
 * @return FRESULT: 操作结果（FR_OK=成功）
 * @note   嵌入式场景极少使用（通常一个物理驱动器对应一个分区）
 */
FRESULT f_fdisk (BYTE pdrv, const LBA_t ptbl[], void* work);

/**
 * @brief  设置当前代码页（字符编码转换用）
 * @param  cp: 代码页编号（如936=GBK，65001=UTF-8）
 * @return FRESULT: 操作结果（FR_OK=成功）
 */
FRESULT f_setcp (WORD cp);

/**
 * @brief  向文件写入一个字符
 * @param  c: 待写入的字符
 * @param  fp: 文件对象指针（已以FA_WRITE模式打开）
 * @return int: 成功返回写入的字符，失败返回EOF（-1）
 */
int f_putc (TCHAR c, FIL* fp);

/**
 * @brief  向文件写入一个字符串
 * @param  str: 待写入的字符串
 * @param  cp: 文件对象指针（已以FA_WRITE模式打开）
 * @return int: 成功返回非负值，失败返回EOF（-1）
 */
int f_puts (const TCHAR* str, FIL* cp);

/**
 * @brief  向文件写入格式化字符串
 * @param  fp: 文件对象指针（已以FA_WRITE模式打开）
 * @param  str: 格式化字符串（如 _T("hello %s!\r\n", "ZN")）
 * @param  ...: 可变参数（与格式化字符串匹配）
 * @return int: 成功返回写入的字符数，失败返回EOF（-1）
 * @note   你的mk_file函数使用此函数写入测试数据
 */
int f_printf (FIL* fp, const TCHAR* str, ...);

/**
 * @brief  从文件读取一个字符串
 * @param  buff: 存储字符串的缓冲区
 * @param  len: 缓冲区长度（包含终止符）
 * @param  fp: 文件对象指针（已以FA_READ模式打开）
 * @return TCHAR*: 成功返回buff指针，失败返回NULL
 */
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp);

/* 部分API通过宏定义实现（简化代码） */
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))	/* 判断是否到达文件尾（fptr==文件大小） */
#define f_error(fp) ((fp)->err)								/* 获取文件操作错误码 */
#define f_tell(fp) ((fp)->fptr)								/* 获取当前文件读写指针位置 */
#define f_size(fp) ((fp)->obj.objsize)						/* 获取文件大小 */
#define f_rewind(fp) f_lseek((fp), 0)						/* 重置文件读写指针到起始位置 */
#define f_rewinddir(dp) f_readdir((dp), 0)					/* 重置目录遍历到起始位置 */
#define f_rmdir(path) f_unlink(path)						/* 删除目录（本质是f_unlink，目录需为空） */
#define f_unmount(path) f_mount(0, path, 0)					/* 卸载驱动器*/


/*----------------------------------------------------------------------------/
/  8. 辅助函数声明                                                           /
/  （需用户实现或FatFs提供，依赖配置）                                        /
/----------------------------------------------------------------------------*/

/* RTC函数（提供文件时间戳，非只读模式必须实现） */
#if !FF_FS_READONLY && !FF_FS_NORTC
DWORD get_fattime (void);	/* 获取当前时间（格式：年<<25 | 月<<21 | 日<<16 | 时<<11 | 分<<5 | 秒>>1） */
#endif

/* 长文件名支持函数（长文件名模式下由ffunicode.c提供） */
#if FF_USE_LFN >= 1
WCHAR ff_oem2uni (WCHAR oem, WORD cp);	/* OEM编码转Unicode */
WCHAR ff_uni2oem (DWORD uni, WORD cp);	/* Unicode转OEM编码 */
DWORD ff_wtoupper (DWORD uni);			/* Unicode字符转大写 */
#endif

/* 操作系统相关函数（动态内存分配/多线程同步，由ffsystem.c提供示例） */
#if FF_USE_LFN == 3		/* 动态内存分配（长文件名模式3专用） */
void* ff_memalloc (UINT msize);		/* 分配内存块 */
void ff_memfree (void* mblock);		/* 释放内存块 */
#endif
#if FF_FS_REENTRANT	/* 多线程同步（可重入模式专用） */
int ff_mutex_create (int vol);		/* 创建同步对象（互斥锁） */
void ff_mutex_delete (int vol);		/* 删除同步对象 */
int ff_mutex_take (int vol);		/* 获取同步对象（加锁） */
void ff_mutex_give (int vol);		/* 释放同步对象（解锁） */
#endif


/*----------------------------------------------------------------------------/
/  9. 宏定义（标志位/偏移量/模式选项）                                        /
/  （API调用时的常用参数，需熟记）                                            /
/----------------------------------------------------------------------------*/

/* 文件打开模式标志（f_open的第三个参数，可组合使用） */
#define	FA_READ				0x01	/* 只读模式 */
#define	FA_WRITE			0x02	/* 只写模式 */
#define	FA_OPEN_EXISTING	0x00	/* 仅打开已存在的文件（不存在则失败） */
#define	FA_CREATE_NEW		0x04	/* 创建新文件（已存在则失败） */
#define	FA_CREATE_ALWAYS	0x08	/* 创建文件（已存在则覆盖） */
#define	FA_OPEN_ALWAYS		0x10	/* 打开文件（不存在则创建） */
#define	FA_OPEN_APPEND		0x30	/* 追加模式（读写指针定位到文件尾） */

/* 快速定位控制（f_lseek的第二个参数） */
#define CREATE_LINKMAP	((FSIZE_t)0 - 1)	/* 创建簇链接映射表（快速定位用） */

/* 格式化选项（f_mkfs的第二个参数） */
#define FM_FAT		0x01	/* 格式化为FAT12/FAT16（根据容量自动选择） */
#define FM_FAT32	0x02	/* 强制格式化为FAT32*/
#define FM_EXFAT	0x04	/* 强制格式化为exFAT（4GB以上大存储用） */
#define FM_ANY		0x07	/* 自动选择文件系统类型（默认值） */
#define FM_SFD		0x08	/* 格式化为单文件系统（嵌入式小存储用） */

/* 文件系统类型（FATFS.fs_type成员值） */
#define FS_FAT12	1	/* FAT12（容量≤4MB） */
#define FS_FAT16	2	/* FAT16（容量4MB~2GB） */
#define FS_FAT32	3	/* FAT32（容量2GB~4GB） */
#define FS_EXFAT	4	/* exFAT（容量4GB~16EB） */

/* 文件属性标志（FILINFO.fattrib成员值，可组合使用） */
#define	AM_RDO	0x01	/* 只读属性（文件不可修改） */
#define	AM_HID	0x02	/* 隐藏属性（目录遍历不显示） */
#define	AM_SYS	0x04	/* 系统属性（系统文件） */
#define AM_DIR	0x10	/* 目录属性 */
#define AM_ARC	0x20	/* 归档属性（文件已修改未备份） */


#ifdef __cplusplus
}
#endif

#endif






